#pragma once

#include "AsyncLibDef.h"

namespace AsyncLib
{

class CThreadpoolWork;
class CThreadpoolTimer;

class CAsyncLib : public IAsyncLib
{
public:
	CAsyncLib();
	~CAsyncLib();

	void Init(ATID atidMax) override;
	void Exit(bool bWaitTasks) override;

	void PostTask(ATID atid, std::function<void()>&& fnTask) override;
	void PostDelayedTask(UINT nMilliseconds, std::function<void()>&& fnTask) override;
	void WaitForAsync(HANDLE handle, UINT nMilliseconds, std::function<void(DWORD)>&& fnCallback) override;

	bool IsInTaskThread(ATID atid) const override;
	bool IsInThreadPool() const override;
	void SetInTaskThread(ATID atid);
	void SetInThreadPool();

	bool IsRunning() const { return m_status == Running; }
	ATID InnerGetAtid() const;
	void InnerPostTask(ATID atid, std::function<void()>&& fnTask);

	std::shared_ptr<ITimerTask> CreateTimerTask(bool bUITimer) override;
	std::shared_ptr<IFileTask> CreateFileTask(HANDLE hFile) override;

private:
	void WaitForAllTasks();
	void InitTaskThreads(ATID atidMax);
	void ExitTaskThreads();
	void InitThreadpools();
	void ExitThreadpools();
	void ProcessCallbacks();

	volatile enum { Exited, Exiting, Running } m_status;
	std::shared_mutex m_mutex;
	std::unique_ptr<CThreadpoolWork>  m_pThreadpoolWork;
	std::unique_ptr<CThreadpoolTimer> m_pThreadpoolTimer;
};

extern CAsyncLib g_asyncLib;

} // namespace AsyncLib
